#!/usr/bin/env python2.5
# encoding: utf-8
"""
stream.py

Created by Alakazam on 2007-07-05.
Copyright (c) 2007 . All rights reserved.
"""

import unittest
from abstract import abstract

class Stream(object):
  # Abstract methods
  def __init__(self): abstract()
  
  def get(self, t): abstract()
  
  def getIter(self, startTime, endTime): abstract()
  
  def getById(self, id): abstract()
  
  def getNextStart(self, t): abstract()
  
  def getNextEnd(self, t): abstract()
  
  def getPreviousStart(self, t): abstract()
  
  def getPreviousEnd(self, t): abstract()
  
  def getFirstStart(self): abstract()
  
  def getLastEnd(self): abstract()
  
  def getMinEventLength(self):
    """
    This function returns the shortest length of an event in the stream
    It is used to choose the maximum zoom factor
    """
    abstract()
  
  def getMaximumValue(self):
    """
    This function is used to choose the vertical scale
    """
    abstract()
  
  def getMinimumValue(self):
    """
    This function is used to choose the vertical scale
    """
    abstract()
  
  def delete(self): abstract()
  
  def __contains__(self, value): abstract()
  
  def __repr__(self): abstract()
  
  
  # Non abstract methods
  def __len__(self):
    return self.getLastEnd() - self.getFirstStart()
  
  def __getitem__(self, key):
    if isinstance(key, slice):
      return self.getIter(key.start, key.stop)
    else:
      return self.get(key)
  
  def __iter__(self):
    return self.getIter(self.getFirstStart(), self.getLastEnd())
  

class TestStream(Stream):
  def __init__(self, value, firstStart, lastEnd):
    self.value      = value
    self.firstStart = firstStart
    self.lastEnd    = lastEnd
  
  def get(self, t):
    return self.value if t >= self.firstStart and t <= self.lastEnd else False
  
  def getIter(self, startTime, endTime):
    if startTime < self.firstStart:
      startTime = self.firstStart
    
    if endTime > self.lastEnd:
      endTime = self.lastEnd
    
    return [
      (startTime + i, startTime + i + 1, self.value)
        for i in range(endTime - startTime)].__iter__()
  
  def getNextStart(self, t):
    return t if t < self.lastEnd else False
  
  def getNextEnd(self, t):
    return t + 1 if t < self.lastEnd else False
  
  def getPreviousStart(self, t):
    return t - 1 if t > self.firstStart else False
  
  def getPreviousEnd(self, t):
    return t if t > self.firstStart else False
  
  def getFirstStart(self):
    return self.firstStart
  
  def getLastEnd(self):
    return self.lastEnd
  
  def getMinEventLength(self):
    return 1
  
  def getMaximumValue(self):
    return self.value
  
  def getMinimumValue(self):
    return self.value
  
  def __contains__(self, value):
    return value == self.value
  

class StreamTests(unittest.TestCase):
  value     = 1
  startTime = 0
  endTime   = 10
  testTime  = 5
  
  def setUp(self):
    self.stream = TestStream(self.value, self.startTime, self.endTime)
  
  def testStream(self):
    """Make certain that we can't instantiate a stream"""
    self.assertRaises(NotImplementedError, Stream)
  
  def testTestStream(self):
    self.assertEqual(
      self.stream.get(self.testTime),
      self.value)
    
    for event in self.stream.getIter(self.startTime, self.endTime):
      self.assert_(event[0] >= self.startTime)
      self.assert_(event[1] <= self.endTime)
      self.assert_(event[2] == self.value)
    
    self.assertEqual(
      self.stream.getNextStart(self.testTime),
      self.testTime)
    
    self.assertEqual(
      self.stream.getNextEnd(self.testTime),
      self.testTime + 1)
    
    self.assertEqual(
      self.stream.getPreviousStart(self.testTime),
      self.testTime - 1)
    
    self.assertEqual(
      self.stream.getPreviousEnd(self.testTime),
      self.testTime)
    
    self.assertEqual(
      self.stream.getFirstStart(),
      self.startTime)
    
    self.assertEqual(
      self.stream.getLastEnd(),
      self.endTime)
    
    self.assertEqual(
      self.stream.getMinEventLength(),
      1)
    
    self.assertEqual(
      self.stream.getMaximumValue(),
      self.value)
    
    self.assertEqual(
      self.stream.getMinimumValue(),
      self.value)
    
    self.assert_(self.value in self.stream)
  
  def testLen(self):
    """Test the length of results returned by __len__()"""
    self.assertEqual(
      len(self.stream),
      self.endTime - self.startTime)
  
  def testIter(self):
    for event in self.stream:
      self.assert_(event[0] >= self.startTime)
      self.assert_(event[1] <= self.endTime)
      self.assert_(event[2] == self.value)
  
  def testGetitem(self):
    for event in self.stream[self.testTime:self.testTime + 1]:
      self.assertEqual(
        event,
        (self.testTime, self.testTime + 1, self.value))
  

if __name__ == '__main__':
  unittest.main()

